package com.bosssoft.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.common.util.Md5Utils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bosssoft.entity.dto.FibUserDTO;
import com.bosssoft.entity.dto.FibUserRoleDTO;
import com.bosssoft.entity.po.FibRolePO;
import com.bosssoft.entity.po.FibUserPO;
import com.bosssoft.entity.vo.FibRoleVO;
import com.bosssoft.entity.vo.FibUserVO;
import com.bosssoft.enums.CopyPropertityEnum;
import com.bosssoft.exception.DaoException;
import com.bosssoft.page.PageResult;
import com.bosssoft.response.Result;
import com.bosssoft.service.*;
import com.bosssoft.util.JwtTokenUtil;
import com.bosssoft.util.MD5Util;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.time.Duration;
import java.util.*;

/**
 * @author 项昊天
 * @create 2021/8/16 16:41
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    FibUserService userService;

    @Resource
    FibUserRoleService userRoleService;

    @Resource
    FibRoleService roleService;

    @Resource
    FibAuthService authService;

    @Resource
    FibRoleAuthService roleAuthService;

    @Autowired
    RedisTemplate redisTemplate;

    @PostMapping("/test")
    public Result test() {
        return Result.ok().message("测试成功");
    }

    @PostMapping("/redistest")
    public Result redistest(@RequestParam("message") String msg) {
        log.info("进来了redistest");

        redisTemplate.opsForValue().set("message", msg);

        String message = (String) redisTemplate.opsForValue().get("message");
        log.info("结束了redistest");
        return Result.ok().message(message);
    }

    @PostMapping("/register")
    public Result register(@RequestBody @Validated FibUserVO userVO,
                           HttpServletRequest request) {
        log.info("进入到注册模块");
        HttpSession session = request.getSession();
        try {
            Byte deleted = 1;
            userVO.setDeleted(deleted);
            userVO.setUserPassword(MD5Util.getMD5(userVO.getUserPassword()));
            FibUserDTO userDTO = new FibUserDTO();
            BeanUtils.copyProperties(userVO, userDTO);
            boolean isRegSus = userService.register(userDTO);
            if (isRegSus) {
                FibUserRoleDTO userRoleDTO = new FibUserRoleDTO();
                userRoleDTO.setUserId(userService.getIdByUsername(userVO.getUserUsername()));
                userRoleDTO.setCreateBy("admin");
                userRoleDTO.setUpdateBy("admin");
                //TODO 换成普通角色的角色id
                userRoleDTO.setRoleId(1L);
                userRoleDTO.setDeleted(deleted);
                userRoleService.addUserRole(userRoleDTO);
                return Result.ok().message("注册成功!");
            }
        } catch (Exception e) {
            log.info("注册异常!");
            throw DaoException.error().setCodeAndMessage(CopyPropertityEnum.RESOURCE_NULL_ERROR);
        }
        log.info("正常通过注册");
        return Result.ok().message("注册成功!");
    }

    /**
     * 分页查询
     *
     * @param current
     * @param pageSize
     * @return
     */
    @PostMapping("/getUserPage")
    public Result getUserPage(@RequestParam(defaultValue = "1") Integer pageNo,
                              @RequestParam(defaultValue = "10") Integer pageSize, FibUserVO fibUserVO) {
        try {
            Page<FibUserPO> page = new Page<>(pageNo, pageSize);
            QueryWrapper<FibUserPO> queryWrapper = new QueryWrapper<>();
            if (fibUserVO.getUserId()!=null&& ObjectUtil.isNotNull(fibUserVO.getUserId())){
                queryWrapper.like("user_id", fibUserVO.getUserId());
            }
            if (fibUserVO.getUserUsername()!=null && ObjectUtil.isNotNull(fibUserVO.getUserUsername())){
                queryWrapper.like("user_username", fibUserVO.getUserUsername() );
            }
            Page<FibUserPO> userPage = userService.page(page, queryWrapper);
            long total = userPage.getTotal();
            List<FibUserPO> recordPOs = userPage.getRecords();
//      List<FibUserVO> recordVOs = new ArrayList<>(recordPOs.pageSize());
//      for (int i = 0; i<recordPOs.pageSize(); ++i) {
//        recordVOs.add(new FibUserVO());
//        BeanUtils.copyProperties(recordPOs.get(i), recordVOs.get(i));
//      }
            PageResult<FibUserPO> results = new PageResult<>(page, recordPOs);
            return Result.ok().data("total", total)
                    .data("page", results)
                    .data("pageNo", pageNo);
        } catch (Exception e) {
            log.info("getUserPage出现异常");
            throw DaoException.error(CopyPropertityEnum.RESOURCE_NULL_ERROR);
        }
    }

    @PutMapping("/modify")
    public Result modifyUser(@RequestBody @Validated FibUserVO userVO) {
        try {
            userVO.setUserPassword(MD5Util.getMD5(userVO.getUserPassword()));
            FibUserDTO userDTO = new FibUserDTO();
            BeanUtils.copyProperties(userVO, userDTO);
            userService.updateUserDetails(userDTO);
            return Result.ok().message("修改成功!");
        } catch (Exception e) {
            throw DaoException.error(CopyPropertityEnum.RESOURCE_NULL_ERROR);
        }
    }

    @DeleteMapping("/delete")
    public Result deleteUser(@RequestBody FibUserVO userVO) {
        if (userVO.getUserId() != null && userService.deleteUserById(userVO.getUserId())) {
            return Result.ok().message("删除用户成功!");
        }
        return Result.error().message("删除用户失败");
    }

    @PutMapping("/ban/{id}/{status}")
    public Result banUser(@PathVariable("id") Long id,
                          @PathVariable("status") Integer status) {
        log.info("进入到userController的banUser方法");
        try {
            if (userService.banUserById(id, status)) {
                return Result.ok().message("操作成功!");
            }
            log.info("结束userController的banUser方法");
            return Result.ok().message("操作失败!");
        } catch (Exception e) {
            log.info("userController的banUser方法抛出异常");
            throw DaoException.error();
        }
    }

    @PostMapping("/login")
    public Result login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        HttpServletRequest request) {
        log.info("进入userController的login方法!");
        log.info("用户名:{},密码:{}", username, password);
        password = MD5Util.getMD5(password);
        log.info("用户名:{},加密后的密码:{}", username, password);
        FibUserDTO userDTO = userService.login(username, password);
        if (userDTO == null) {
            log.info("用户名或密码错误!");
            return Result.error().message("用户名或密码错误!");
        }
        FibUserVO userVO = new FibUserVO();
        try {
            BeanUtils.copyProperties(userDTO, userVO);
            if (username.equals(userVO.getUserUsername())) {
                log.info("已经判断登录成功了");
                Long userId = userService.getIdByUsername(username);
                log.info("userId:{}", userId);
                //拿到roleId
                Long roleId = userRoleService.getRoleByUserId(userId);
                log.info("roleId:{}", roleId);
                //拿到角色名
                String roleName = roleService.getRoleNameById(roleId);
                log.info("roleName:{}", roleName);
                //拿到所有角色所对应的权限id
                List<Long> allAuthId = roleAuthService.getAllAuthIdByRoleId(roleId);
                log.info("allAuthId:{}", allAuthId);
                //拿到所能访问的url
                List<String> accessUrls = new ArrayList<>(allAuthId.size());
                for (Long authId : allAuthId) {
                    String url = authService.getUrlById(authId);
                    accessUrls.add(url);
                }
                log.info("拿到了能访问的url:{}", accessUrls);
                //向token里面放东西
                Map<String, Object> map = new HashMap<>(3);
                map.put("jti", userId);
                map.put("sub", username);
                map.put("iat", new Date());
                map.put("roleName", roleName);
                map.put("accessUrls", accessUrls);

                // 生成token
                String token = JwtTokenUtil.generateToken(map);

                // 往redis里面放token,其中token 为 键, username用户名 为 值
                redisTemplate.opsForValue().set(token, username, Duration.ofMillis(JwtTokenUtil.getTokenExp(token)));
                log.info("毫秒值:{}", Duration.ofMillis(JwtTokenUtil.getTokenExp(token)));
                log.info("day:{}", Duration.ofDays(JwtTokenUtil.getTokenExp(token)));
                log.info("登录成功!");
                return Result.ok().message("登录成功!").data("token", token).data("roleId", roleId).data("roleName", roleName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw DaoException.error(CopyPropertityEnum.RESOURCE_NULL_ERROR);
        }
        log.info("登录验证失败");
        return Result.error().message("用户名或密码错误!");
    }
}
